﻿using Abp.Authorization;
using Abp.Runtime.Session;
using Abp.Specifications;
using Paas.App.Interface.Sys.Data;
using Paas.App.Interface.Sys.Data.Dtos;
using Paas.App.Interface.Sys.Data.Messages;
using Paas.Core;
using Paas.Core.Sys.Entities;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Basefr.App;
using Basefr.Core.Extensions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using IdNameDataDto = Paas.App.Interface.Sys.Data.Dtos.IdNameDataDto;

namespace Paas.App.Sys
{
    [Route("Sys-Data")]
    [AbpAuthorize()]
    public class SysDataAppService : AppService, ISysDataAppService
    {
        private readonly IMainRepository<Organization> _organRepo;
        private readonly IMainRepository<User, long> _userRepo;

        public SysDataAppService(
            IMainRepository<Organization> organRepo,
            IMainRepository<User, long> userRepo)
        {
            _organRepo = organRepo;
            _userRepo = userRepo;
        }


        [HttpPost(nameof(SearchAvailableOrganization))]
        public virtual SearchAvailableOrganizationOutput SearchAvailableOrganization(SearchAvailableOrganizationInput input)
        {
            if (string.IsNullOrWhiteSpace(input.Name) && input.IsDefaultEmpty)
            {
                return new SearchAvailableOrganizationOutput { Items = new List<OrganizationDataDto>() };
            }

            input.Name = input.Name?.Trim();

            var organs = _organRepo.GetAll()
                .Include(p => p.Parent.Parent.Parent.Parent.Parent)
                .Include(p => p.Children)
                .Where(p => string.IsNullOrWhiteSpace(input.Name) || p.Name.Contains(input.Name))
                .OrderBy(p => p.Id)
                .ToList()
                .FindAll(p => p.ParentId == null);

            return new SearchAvailableOrganizationOutput { Items = ObjectMapper.Map<List<OrganizationDataDto>>(organs) };
        }

        [HttpPost(nameof(SearchAvailableUser))]
        public virtual SearchAvailableUserOutput SearchAvailableUser(SearchAvailableUserInput input)
        {
            if (string.IsNullOrWhiteSpace(input.Name) && input.IsDefaultEmpty)
            {
                return new SearchAvailableUserOutput { Items = new List<IdNameDataDto>() };
            }

            var currentUser = _userRepo.Get(AbpSession.GetUserId());

            input.Name = input.Name?.Trim();

            Expression<Func<User, bool>> predicate = p => !string.IsNullOrWhiteSpace(input.Name);

            predicate = predicate.And(p => p.Name.Contains(input.Name) || p.UserName.Contains(input.Name));

            if (input.FilterByOrganization)
            {
                if (currentUser.IsLeader)
                {
                    predicate = predicate.And(p =>
                        p.OrganizationId == currentUser.OrganizationId ||
                        p.Organization.Parent.Id == currentUser.OrganizationId ||
                        p.Organization.Parent.Parent.Id == currentUser.OrganizationId ||
                        p.Organization.Parent.Parent.Parent.Id == currentUser.OrganizationId ||
                        p.Organization.Parent.Parent.Parent.Parent.Id == currentUser.OrganizationId ||
                        p.Organization.Parent.Parent.Parent.Parent.Parent.Id == currentUser.OrganizationId);
                }
                else
                {
                    predicate = predicate.And(p => p.Id == AbpSession.GetUserId());
                }
            }

            var users = _userRepo.GetAll()
                .Include(p => p.Organization.Parent.Parent.Parent.Parent.Parent)
                .Where(predicate)
                .OrderBy(p => p.Name)
                .ToList();

            return new SearchAvailableUserOutput { Items = ObjectMapper.Map<List<IdNameDataDto>>(users) };
        }

    }
}

